#include "stdafx.h"
#include "colorspace.h"

#if defined(_WIN64)
static inline unsigned char vlc_uint8( int v )
{
    if( v > 255 )
        return 255;
    else if( v < 0 )
        return 0;
    return v;
}
static void Yuv2Rgb( unsigned char *r, unsigned char *g, unsigned char *b, int y1, int u1, int v1 )
{
    /* macros used for YUV pixel conversions */
#   define SCALEBITS 10
#   define ONE_HALF  (1 << (SCALEBITS - 1))
#   define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))

    int y, cb, cr, r_add, g_add, b_add;

    cb = u1 - 128;
    cr = v1 - 128;
    r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
    g_add = - FIX(0.34414*255.0/224.0) * cb
            - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
    b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
    y = (y1 - 16) * FIX(255.0/219.0);
    *r = vlc_uint8( (y + r_add) >> SCALEBITS );
    *g = vlc_uint8( (y + g_add) >> SCALEBITS );
    *b = vlc_uint8( (y + b_add) >> SCALEBITS );
#undef FIX
}

void f_yuv12_2_rgb24(unsigned char * dst,int dst_stride,
					 unsigned char * y_src,
		unsigned char * v_src,
		unsigned char * u_src,
		int y_stride,
		int uv_stride,
		int width,
		int height
		)
{
	int				area = width * height;
	int				width_2 = width >> 1;
	int				width3 = dst_stride * 3;
	int				height_2 = height >> 1;
	int				width4 = uv_stride;
	unsigned char*	yline0 = y_src;
	unsigned char*	yline1 = y_src + y_stride; //src + width;
	unsigned char*	upos = v_src; //src + area;
	unsigned char*	vpos = u_src; //upos + (area >> 2);
	unsigned char*	rgbline0 = dst;
	unsigned char*	rgbline1 = dst + width3;

	for (int i = 0; i < height_2; i++) {
		for (int j = 0; j < width_2; j++) {
			unsigned char	y00 = *yline0++;
			unsigned char	y01 = *yline0++;
			unsigned char	y10 = *yline1++;
			unsigned char	y11 = *yline1++;
			unsigned char	u = *upos++;
			unsigned char	v = *vpos++;
#if 0
			unsigned char r,g,b;
			Yuv2Rgb( &r,&g,&b, y00,u, v);
			*rgbline0++ = b;
			*rgbline0++ = g;
			*rgbline0++ = r;
			Yuv2Rgb(&r,&g,&b, y01,u, v);
			*rgbline0++ = b;
			*rgbline0++ = g;
			*rgbline0++ = r;
			Yuv2Rgb(&r,&g,&b, y10,u, v);
			*rgbline1++ = b;
			*rgbline1++ = g;
			*rgbline1++ = r;
			Yuv2Rgb( &r,&g,&b, y11,u, v);
			*rgbline1++ = b;
			*rgbline1++ = g;
			*rgbline1++ = r;
#endif
#if 1
			int				Y, U, V;
			int				R, G, B;
			U = u;	U -= 128;
			V = v;	V -= 128;

			Y = y00;	Y <<= 15;
			R = (Y + 44915 * V) >> 15;
			G = (Y - 22872 * V - 11064 * U) >> 15;
			B = (Y + 56769 * U) >> 15;
			if (R > 255)
				R = 255;
			if (G > 255)
				G = 255;
			if (B > 255)
				B = 255;
			if (R < 0)
				R = 0;
			if (G < 0)
				G = 0;
			if (B < 0)
				B = 0;
			*rgbline0++ = (unsigned char) (B);
			*rgbline0++ = (unsigned char) (G);
			*rgbline0++ = (unsigned char) (R);

			Y = y01;	Y <<= 15;
			R = (Y + 44915 * V) >> 15;
			G = (Y - 22872 * V - 11064 * U) >> 15;
			B = (Y + 56769 * U) >> 15;
			if (R > 255)
				R = 255;
			if (G > 255)
				G = 255;
			if (B > 255)
				B = 255;
			if (R < 0)
				R = 0;
			if (G < 0)
				G = 0;
			if (B < 0)
				B = 0;
			*rgbline0++ = (unsigned char) (B);
			*rgbline0++ = (unsigned char) (G);
			*rgbline0++ = (unsigned char) (R);

			Y = y10;	Y <<= 15;
			R = (Y + 44915 * V) >> 15;
			G = (Y - 22872 * V - 11064 * U) >> 15;
			B = (Y + 56769 * U) >> 15;
			if (R > 255)
				R = 255;
			if (G > 255)
				G = 255;
			if (B > 255)
				B = 255;
			if (R < 0)
				R = 0;
			if (G < 0)
				G = 0;
			if (B < 0)
				B = 0;
			*rgbline1++ = (unsigned char) (B);
			*rgbline1++ = (unsigned char) (G);
			*rgbline1++ = (unsigned char) (R);

			Y = y11;	Y <<= 15;
			R = (Y + 44915 * V) >> 15;
			G = (Y - 22872 * V - 11064 * U) >> 15;
			B = (Y + 56769 * U) >> 15;
			if (R > 255)
				R = 255;
			if (G > 255)
				G = 255;
			if (B > 255)
				B = 255;
			if (R < 0)
				R = 0;
			if (G < 0)
				G = 0;
			if (B < 0)
				B = 0;
			*rgbline1++ = (unsigned char) (B);
			*rgbline1++ = (unsigned char) (G);
			*rgbline1++ = (unsigned char) (R);
#endif
		}
		yline0 += y_stride;
		yline1 += y_stride;
		rgbline0 += width3;
		rgbline1 += width3;
	}
}

void f_yuv12_2_rgb32
	(
	unsigned char * dst,
	int dst_stride,
	unsigned char * y_src,
	unsigned char * v_src,
	unsigned char * u_src,
	int y_stride,
	int uv_stride,
	int width,
	int height
	)
{
	int				area = width * height;
	int				width_2 = y_stride>>1; //width >> 1;
	int				width3 = dst_stride * 4;
	int				height_2 = height >> 1;
	int				width4 = uv_stride;
	unsigned char*	yline0 = y_src;
	unsigned char*	yline1 = y_src + y_stride; //src + width;
	unsigned char*	upos = v_src; //u_src; //src + area;
	unsigned char*	vpos = u_src; //upos + (area >> 2);
	unsigned char*	rgbline0 = dst;
	unsigned char*	rgbline1 = dst + width3;

	for (int i = 0; i < height_2; i++) {
		for (int j = 0; j < width_2; j++) {
			unsigned char	y00 = *yline0++;
			unsigned char	y01 = *yline0++;
			unsigned char	y10 = *yline1++;
			unsigned char	y11 = *yline1++;
			unsigned char	u = *upos++;
			unsigned char	v = *vpos++;

#if 1
			unsigned char r,g,b;
			Yuv2Rgb( &r,&g,&b, y00,u, v);
			*rgbline0++ = b;
			*rgbline0++ = g;
			*rgbline0++ = r;
			*rgbline0++ = 0;
			Yuv2Rgb(&r,&g,&b, y01,u, v);
			*rgbline0++ = b;
			*rgbline0++ = g;
			*rgbline0++ = r;
			*rgbline0++ = 0;
			Yuv2Rgb(&r,&g,&b, y10,u, v);
			*rgbline1++ = b;
			*rgbline1++ = g;
			*rgbline1++ = r;
			*rgbline1++ = 0;
			Yuv2Rgb( &r,&g,&b, y11,u, v);
			*rgbline1++ = b;
			*rgbline1++ = g;
			*rgbline1++ = r;
			*rgbline1++ = 0;
#endif
#if 0
			int				Y, U, V;
			int				R, G, B;
			U = u;	U -= 128;
			V = v;	V -= 128;

			Y = y00;	Y <<= 15;
			R = (Y + 44915 * V) >> 15;
			G = (Y - 22872 * V - 11064 * U) >> 15;
			B = (Y + 56769 * U) >> 15;
			if (R > 255)
				R = 255;
			if (G > 255)
				G = 255;
			if (B > 255)
				B = 255;
			if (R < 0)
				R = 0;
			if (G < 0)
				G = 0;
			if (B < 0)
				B = 0;
			
			*rgbline0++ = (unsigned char) (B);
			*rgbline0++ = (unsigned char) (G);
			*rgbline0++ = (unsigned char) (R);
			*rgbline0++ = 0;
			
			Y = y01;	Y <<= 15;
			R = (Y + 44915 * V) >> 15;
			G = (Y - 22872 * V - 11064 * U) >> 15;
			B = (Y + 56769 * U) >> 15;
			if (R > 255)
				R = 255;
			if (G > 255)
				G = 255;
			if (B > 255)
				B = 255;
			if (R < 0)
				R = 0;
			if (G < 0)
				G = 0;
			if (B < 0)
				B = 0;
			
			*rgbline0++ = (unsigned char) (B);
			*rgbline0++ = (unsigned char) (G);
			*rgbline0++ = (unsigned char) (R);
			*rgbline0++ = 0;
			
			

			Y = y10;	Y <<= 15;
			R = (Y + 44915 * V) >> 15;
			G = (Y - 22872 * V - 11064 * U) >> 15;
			B = (Y + 56769 * U) >> 15;
			if (R > 255)
				R = 255;
			if (G > 255)
				G = 255;
			if (B > 255)
				B = 255;
			if (R < 0)
				R = 0;
			if (G < 0)
				G = 0;
			if (B < 0)
				B = 0;
			
			*rgbline1++ = (unsigned char) (B);
			*rgbline1++ = (unsigned char) (G);
			*rgbline1++ = (unsigned char) (R);
			*rgbline1++ = 0;
			

			Y = y11;	Y <<= 15;
			R = (Y + 44915 * V) >> 15;
			G = (Y - 22872 * V - 11064 * U) >> 15;
			B = (Y + 56769 * U) >> 15;
			if (R > 255)
				R = 255;
			if (G > 255)
				G = 255;
			if (B > 255)
				B = 255;
			if (R < 0)
				R = 0;
			if (G < 0)
				G = 0;
			if (B < 0)
				B = 0;
			
			*rgbline1++ = (unsigned char) (B);
			*rgbline1++ = (unsigned char) (G);
			*rgbline1++ = (unsigned char) (R);
			*rgbline1++ = 0;	
#endif
		}

		yline0 += y_stride;
		yline1 += y_stride;
		rgbline0 += width3;
		rgbline1 += width3;
	}
}

void f_yuv12_2_rgb555
	(
	unsigned char * dst,
	int dst_stride,
	unsigned char * y_src,
	unsigned char * v_src,
	unsigned char * u_src,
	int y_stride,
	int uv_stride,
	int width,
	int height
	)
{
}

void f_yuv12_2_rgb565
	(
	unsigned char * dst,
	int dst_stride,
	unsigned char * y_src,
	unsigned char * v_src,
	unsigned char * u_src,
	int y_stride,
	int uv_stride,
	int width,
	int height
	)
{

}


void f_yuy2_2_rgb555
		(
		unsigned char * dst,
		int dst_stride,
		unsigned char * src,
		int src_stride,
		int width,
		int height
		)
{
}

void f_yuy2_2_rgb565
		(
		unsigned char * dst,
		int dst_stride,
		unsigned char * src,
		int src_stride,
		int width,
		int height
		)
{
}

void f_yuy2_2_rgb24
		(
		unsigned char * dst,
		int dst_stride,
		unsigned char * src,
		int src_stride,
		int width,
		int height
		)
{
	int				width_2 = src_stride>>1; //width >> 1;
	int				height_2 = height >> 1;
	unsigned char*	yline0 = src;
	unsigned char*	rgbline0 = dst;

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width_2; j++) {
			unsigned char	y00 = *yline0++;
			unsigned char	u = *yline0++;
			unsigned char	y01 = *yline0++;
			unsigned char	v = *yline0++;

			unsigned char r,g,b;
			Yuv2Rgb( &r,&g,&b, y00,u, v);
			*rgbline0++ = b;
			*rgbline0++ = g;
			*rgbline0++ = r;
			Yuv2Rgb(&r,&g,&b, y01,u, v);
			*rgbline0++ = b;
			*rgbline0++ = g;
			*rgbline0++ = r;
		}
	}
}

void f_yuy2_2_rgb32(unsigned char * dst, int dst_stride,	unsigned char * src, int src_stride,int width,int height)
{
	int				width_2 = src_stride>>1; //width >> 1;
	int				height_2 = height >> 1;
	unsigned char*	yline0 = src;
	unsigned char*	rgbline0 = dst;

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width_2; j++) {
			unsigned char	y00 = *yline0++;
			unsigned char	u = *yline0++;
			unsigned char	y01 = *yline0++;
			unsigned char	v = *yline0++;

			unsigned char r,g,b;
			Yuv2Rgb( &r,&g,&b, y00,u, v);
			*rgbline0++ = b;
			*rgbline0++ = g;
			*rgbline0++ = r;
			*rgbline0++ = 0;
			Yuv2Rgb(&r,&g,&b, y01,u, v);
			*rgbline0++ = b;
			*rgbline0++ = g;
			*rgbline0++ = r;
			*rgbline0++ = 0;
		}
	}
}

ColorSpaceDll::ColorSpaceDll()
{
	m_inited = true;
	yuv12_2_rgb24 = f_yuv12_2_rgb24;
	yuv12_2_rgb32 = f_yuv12_2_rgb32;
	yuv12_2_rgb555 = f_yuv12_2_rgb555;
	yuv12_2_rgb565 = f_yuv12_2_rgb555;

	yuy2_2_rgb555 = f_yuy2_2_rgb555;
	yuy2_2_rgb565 = f_yuy2_2_rgb565;
	yuy2_2_rgb24 = f_yuy2_2_rgb24;
	yuy2_2_rgb32 = f_yuy2_2_rgb32;
}

ColorSpaceDll::~ColorSpaceDll()
{

}

#else
ColorSpaceDll::ColorSpaceDll()
{
	m_inited = true;
#if defined(_UNICODE)
	const wchar_t * dll_name = _T("colorspacedll.dll");
	m_dll  = ::LoadLibrary(dll_name);
#else
	const char* dll_name = "colorspacedll.dll";
	m_dll  = ::LoadLibrary(dll_name);
#endif
	if(!m_dll)
		m_inited = false;

	yuv12_2_rgb24 = reinterpret_cast<dll_yuv12_2_rgb24>(::GetProcAddress(m_dll, ("yuv12_2_rgb24")));
	if(!yuv12_2_rgb24)
		m_inited = false;

	yuv12_2_rgb32 = reinterpret_cast<dll_yuv12_2_rgb32>(::GetProcAddress(m_dll, ("yuv12_2_rgb32")));
	if(!yuv12_2_rgb32)
		m_inited = false;


	yuv12_2_rgb555 = reinterpret_cast<dll_yuv12_2_rgb555>(::GetProcAddress(m_dll, ("yuv12_2_rgb555")));
	if(!yuv12_2_rgb555)
		m_inited = false;


	yuv12_2_rgb565 = reinterpret_cast<dll_yuv12_2_rgb565>(::GetProcAddress(m_dll, ("yuv12_2_rgb565")));
	if(!yuv12_2_rgb565)
		m_inited = false;



	yuy2_2_rgb555 = reinterpret_cast<dll_yuy2_2_rgb555>(::GetProcAddress(m_dll, ("yuy2_2_rgb555")));
	if(!yuv12_2_rgb565)
		m_inited = false;

	yuy2_2_rgb565 = reinterpret_cast<dll_yuy2_2_rgb565 >(::GetProcAddress(m_dll, ("yuy2_2_rgb565")));
	if(!yuv12_2_rgb565)
		m_inited = false;

	yuy2_2_rgb24 = reinterpret_cast<dll_yuy2_2_rgb24 >(::GetProcAddress(m_dll, ("yuy2_2_rgb24")));
	if(!yuy2_2_rgb24)
		m_inited = false;

	yuy2_2_rgb32 = reinterpret_cast<dll_yuy2_2_rgb32>(::GetProcAddress(m_dll, ("yuy2_2_rgb32")));
	if(!yuy2_2_rgb24)
		m_inited = false;
}
ColorSpaceDll::~ColorSpaceDll()
{
	::FreeLibrary(m_dll);
}
#endif
